<?php
namespace App\Common\Server\Api\Gateway;

use App\Common as com;
use App as nameApp;
use App\Common\Server\Api as nameApi;
use App\Common\Server\Api\Gateway as nameGateway;
// use think\facade\App;

class ApiRouter extends nameApi\Base {

	/**
	 * @param ApiRequest $apiRequest api请求对象
	 */
	public function __construct( private nameGateway\ApiRequest $apiRequest ) {
		parent::__construct();
	}

	/**
	 * @return ApiRequest
	 */
	public function apiRequest(  ):nameGateway\ApiRequest {
		return $this->apiRequest;
	}

	/**
	 * api类实体池
	 * @var array
	 */
	private array $apiClassEntityPool = [];

	/**
	 * 检查api是否存在
	 * @return bool [true]存在 [false]不存在
	 */
	public function isExist():bool {
		$apiClassPath = $this->getApiClassPath();
		return method_exists( $apiClassPath, 'excApi' );
	}

	/**
	 * api实体对象
	 * @return nameApp\Api\Application\Base
	 * @throws
	 */
	public function apiClassEntity(  ):nameApp\Api\Application\Base {
		$apiClassPath = $this->getApiClassPath();
		// 检测api池是否存在api对象
		if( ! array_key_exists( $apiClassPath, $this->apiClassEntityPool ) ) {
			// 检查类是否存在
			if( ! class_exists( $apiClassPath ) ){
				throw com\Lib\Err\Exception::makeOfNew( "API不存在({$apiClassPath})", com\Lib\Err\Code::$apiSysApiNoExist );
			}
			// 放入api池
			$this->apiClassEntityPool[ $apiClassPath ] = (new $apiClassPath( $this->apiRequest() ));
		}
		//
		return $this->apiClassEntityPool[ $apiClassPath ];
	}

	/**
	 * 执行api
	 * @return nameGateway\ApiResponse
	 * @throws
	 */
	public function excApi():nameGateway\ApiResponse {
		if( ! $this->isExist() ){
			throw com\Lib\Err\Exception::makeOfNew( '{msg}(' . $this->apiRequest()->apiData()->getApiName() . ')', com\Lib\Err\Code::$apiSysApiNoExist );
		}
		// 创建apiParamDto
		$apiParamDto = nameApi\Lib\ApplicationParamDto::makeByApiRequest( $this->apiRequest() );
		// 执行api
		$apiResponse = $this->apiClassEntity()->excApi( $this->apiRequest(), $apiParamDto );
		// 返回api响应对象
		if( $apiResponse instanceof nameGateway\ApiResponse ){
			return $apiResponse;
		}elseif( is_array( $apiResponse ) ){
			// 转为响应对象->成功
			return nameGateway\ApiResponse::instanceOfSuccess( $apiResponse );
		}else{
			// 错误
			return nameGateway\ApiResponse::instanceOfCommon( com\Lib\Err\Code::$apiSysExecuteError );
		}
	}

	/**
	 * 获取api类路径(app命名空间下的类路径)
	 * @return string
	 */
	private function getApiClassPath( ):string {
		// @todo 这里可以考虑加一个缓存，下次直接读取缓存中的api路径
		// 每个api目录转驼峰
		$apiArray = explode( '.', $this->apiRequest()->apiData()->getApiNameFull() );
		foreach ( $apiArray as &$apiArrayValue ){
			$apiArrayValue = com\Lib\Fun\Str::parseName( $apiArrayValue, 1 );
		} unset( $apiArrayValue );
		// api目录
		return 'App\\Api\\Application\\' . implode( '\\', $apiArray );
		// 版本号>1时需要加入版本号路径
		/*
		if( $this->apiRequest()->apiData()->getVersion() > 1 ){
			$apiClassPath = $apiClassPath . 'V' . $this->apiRequest()->apiData()->getVersion();
		}
		*/
	}

}
